#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <Adafruit_NeoPixel.h>
#include <WidgetRTC.h>
#include <DHT.h>
#define RGB_PIN 12//RGB灯带连接管脚
#define DHTPIN 2//DHT11传感器连接管脚
#define HUMPIN 0//显示湿度按钮连接管脚
#define TEMPPIN 5//显示温度按钮连接管脚

#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
//定义每个数字对应的RGB灯序号
#define POS_MIN 0//分钟个位数
#define POS_TENMIN 14//分钟十位数
#define POS_DOTS 28//小数点
#define POS_HOUR 30//小时个位数
#define POS_TENHOUR 44//小时十位数
#define RGB_NUM 58//RGB灯总数量

Adafruit_NeoPixel strip = Adafruit_NeoPixel(RGB_NUM, RGB_PIN, NEO_GRB + NEO_KHZ800);
byte ss_dec;//秒钟个位
byte ss_dig;//秒钟十位
byte mm_dec;//分钟个位
byte mm_dig;//分钟十位
byte hh_dec;//小时个位
byte hh_dig;//小时十位

byte temp_tens;//温度十位
byte temp_dig;//温度个位
byte temp_tenths;//温度十分位

byte hum_tens;//湿度十位
byte hum_dig;//湿度个位
byte hum_tenths;//湿度十分位

byte current_sec;//当前秒数

char auth[] = "f606c58af305462e946506030b40fb8a";//授权码
char ssid[] = "Maker Space";//wifi名称
char pass[] = "20140811";//wifi密码
boolean dot = false;
int random_color = 20;
int rainbow;
int DisplayType = 0; //显示数据类型，0:时间;1:温度;2:湿度
int displayTempTime=0;//标记显示温度或湿度的时间
BlynkTimer timer;
WidgetRTC rtc;//创建Blynk rtc组件
/*数码管顺序
    -2-
   1   3
    -0-
   6   4
    -5-
*/
byte digit_bits[] = {
  0b01111110, //0
  0b00011000, //1
  0b01101101, //2
  0b00111101, //3
  0b00011011, //4
  0b00110111, //5
  0b01110111, //6
  0b00011100, //7
  0b01111111, //8
  0b00111111, //9
  0b01100110,//C
  0b01001111//P
};

void setNum(int digit, byte number) {//点亮数字
  if (number >= 0 && number <= 10) {
    byte mask = 0x01;
    for (int i = 0; i < 7; i++) {
      if (mask & digit_bits[number] )
      {
        strip.setPixelColor(digit + 2 * i, Wheel( random_color & 255));
        strip.setPixelColor(digit + 2 * i + 1, Wheel( random_color & 255));
        strip.show();
      }
      else
      {
        strip.setPixelColor(digit + 2 * i, strip.Color(0, 0, 0));
        strip.setPixelColor(digit + 2 * i + 1, strip.Color(0, 0, 0));
        strip.show();
      }
      mask <<= 1;
    }
  }
}

void setClockDot(int digit)//点亮时间分割点
{
  if (dot)
  {
    for (int i = 0; i < 2; i++)
    {
      strip.setPixelColor(digit + i, Wheel( random_color & 255));
    }
    strip.show();
  }
  else
  {
    for (int i = 0; i < 2; i++)
    {
      strip.setPixelColor(digit + i, strip.Color(0, 0, 0));
    }
    strip.show();
  }
  dot = !dot;
}
void setTempDot()//点亮温湿度分割点
{
  strip.setPixelColor(POS_DOTS, Wheel( random_color & 255));
  strip.show();
}
void tempDisplay()//显示温度
{
  float Temperature = dht.readTemperature(); //摄氏度
  temp_tens = Temperature / 10;
  temp_dig = (Temperature - temp_tens * 10) * 0.1;
  temp_tenths = (Temperature - temp_tens * 10 - temp_dig) * 10;
  setNum(POS_MIN, 10);//显示符号C
  setNum(POS_TENMIN, temp_tenths);
  setNum(POS_HOUR, temp_dig);
  setNum(POS_TENHOUR, temp_tens);
  setTempDot();
  Serial.print(temp_tens);
  Serial.print(temp_dig);
  Serial.print(".");
  Serial.println(temp_tenths);
}
void humDisplay()//显示湿度
{
  float Humidity = dht.readHumidity();
  hum_tens = Humidity / 10;
  hum_dig = (Humidity - hum_tens * 10) * 0.1;
  hum_tenths = (Humidity - hum_tens * 10 - hum_dig) * 10;
  setNum(POS_MIN, 11);//显示湿度符号H
  setNum(POS_TENMIN, hum_tenths);
  setNum(POS_HOUR, hum_dig);
  setNum(POS_TENHOUR, hum_tens);
  setTempDot();
  Serial.print(hum_tens);
  Serial.print(hum_dig);
  Serial.print(".");
  Serial.println(hum_tenths);
  // setDot(TEMP_DOT);
}

void clockDisplay()//显示时间
{
  ss_dec = second() * 0.1;
  if (current_sec != ss_dec)
  { //每隔10秒换颜色
    random_color = random(1, 180);
  }
  current_sec = ss_dec;
  ss_dig = second() - ss_dec * 10;
  mm_dec = minute() * 0.1;
  mm_dig = minute() - mm_dec * 10;
  hh_dec = hour() * 0.1;
  hh_dig = hour() - hh_dec * 10;
  setNum(POS_MIN, mm_dig);
  setNum(POS_TENMIN, mm_dec);
  setNum(POS_HOUR, hh_dig);
  setNum(POS_TENHOUR, hh_dec);
  setClockDot(POS_DOTS);
}
BLYNK_CONNECTED() {
  rtc.begin();//连上网络后同步时间
}
uint32_t Wheel(byte WheelPos) {//色轮
  if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
void bootRainBow()//开机彩虹效果
{
  strip.begin();
  strip.setBrightness(100);
  rainbow = random(1, 180);
  for (int i = 0; i < strip.numPixels(); i++)
  { //开机亮彩虹
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + rainbow) & 255));
    strip.show();
    delay(40);
  }
  for (int i = strip.numPixels(); i >= 0; i--)
  { //开机灭彩虹
    strip.setPixelColor(i, 0, 0, 0);
    strip.show();
    delay(40);
  }
}
void displayHum() {//按下显示湿度按钮，将显示类型修改为2，即湿度
  DisplayType = 2;
}

void displayTemp() {//按下显示温度按钮，将显示类型修改为1，即温度
  DisplayType = 1;
}

void Display()
{
  if (DisplayType == 0|| displayTempTime==5) //显示时间
  {
    clockDisplay();
     DisplayType=0;
    displayTempTime=0;
  }
  else if (DisplayType == 1&&displayTempTime<5) //显示温度
  {
    tempDisplay();
    displayTempTime++;
  }
  else if(DisplayType == 2&&displayTempTime<5)//显示湿度
  {
    humDisplay();
    displayTempTime++;
  }
}
void setup()
{
  bootRainBow();//开机彩虹效果
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass, IPAddress(192, 168, 31, 249), 8080);//自建服务器ip模式
  setSyncInterval(10 * 60); // 设置同步间隔时间10分钟。
  timer.setInterval(1000L, Display);//每隔1s，运行clockDisplay，显示时间
  attachInterrupt(digitalPinToInterrupt(HUMPIN), displayHum, RISING);
  attachInterrupt(digitalPinToInterrupt(TEMPPIN), displayTemp, RISING);
}
void loop()
{
  Blynk.run();
  timer.run();
}
